﻿using System.Reflection;
using FreeSqlTest.BackgroundServices;
using Natasha.CSharp;
using OrmTestDomain;

namespace FreeSqlTest;

public class NatashaQueryBuilder
{
    public NatashaQueryBuilder()
    {

        NatashaInitializer.Preheating((asmName, name) =>
        {
            var system = PrepareSystem(asmName, name);

            if (system)
            {
                if (name.Contains("Natasha"))
                {
                    //加载
                    return false;
                }

                if (name.Contains("ConsoleApp3"))
                {
                    //加载
                    return false;
                }
            }


            return true;
        });
        GetNatashaDomain();
    }

    private static NatashaReferenceDomain? NatashaReferenceDomain;
    public NatashaReferenceDomain GetNatashaDomain()
    {
        if (NatashaReferenceDomain != null)
        {
            return NatashaReferenceDomain;
        }

        NatashaReferenceDomain=  NatashaManagement.CreateDomain("FreeSqlQuery");

        //预热 Natasha
        NatashaManagement.Preheating();
//增加全局的 Using 引用
        NatashaManagement.AddGlobalUsing("System.IO");
        NatashaManagement.AddGlobalUsing("System");
        var freeSqlNameSpaces = typeof(IFreeSql)
            .Assembly
            .GetTypes()
            .Select(x => x.Namespace)
            .Where(y => string.IsNullOrEmpty(y)).Distinct().ToList();
        foreach (var freeSqlNameSpace in freeSqlNameSpaces)
        {
            NatashaManagement.AddGlobalUsing("freeSqlNameSpace");
        }
        NatashaManagement.AddGlobalReference(typeof(IFreeSql));
        return NatashaReferenceDomain;
    }

    public  IList<UseDto> BuilerBuiderSelect(IFreeSql freeSql)
    {



        NatashaManagement.AddGlobalReference(typeof(UserSplitEntity));
        NatashaManagement.AddGlobalReference(typeof(UserExtendEntity));
        NatashaManagement.AddGlobalReference(typeof(RoleEntity));
        NatashaManagement.AddGlobalReference(typeof(UseDto));



        var action = FastMethodOperator.UseDomain(GetNatashaDomain())
            .Param<IFreeSql>("freeSql")
            .Using(typeof(UserSplitEntity).Namespace)
            .Using(typeof(UserExtendEntity).Namespace)
            .Using(typeof(RoleEntity).Namespace)
            .Using(typeof(UseDto).Namespace)

            .Body(@"var select =
            freeSql.Select<UserSplitEntity, UserExtendEntity, RoleEntity>()
                .LeftJoin((a, b, c) => b.UserId == a.Id)
                .LeftJoin((a, b, c) => b.UserRoleId == c.Id);
        select = select.Where((a, b, c) => c.Id > 0);
        var list = select
            .ToList((a, b, c) => new UseDto
            {
                BirthDate = b.BirthDate,
                Age = b.Age,
                Id = a.Id,
                Name = a.Name,
                RoleName = c.RoleName
            });
            return list;
")
            .Return<string>()
            .Compile<Func<IFreeSql, IList<UseDto>>>();

        return action(freeSql);
    }

    private bool PrepareSystem(AssemblyName assmbilyName, string? name)
    {
        if (name != null)
        {
            if (name.Contains("System"))
            {
                if (
                    name.Contains("Net") ||
                    name.Contains("Xml") ||
                    name.Contains("IO") ||
                    name.Contains("Reflection") ||
                    name.Contains("Threading") ||
                    name.Contains("Security") ||
                    name.Contains("Diagnostics") ||
                    name.Contains("Data") ||
                    name.Contains("Resources.") ||
                    name.Contains("Drawing") ||
                    name.Contains("Text") ||
                    name.Contains("Globalization") ||
                    name.Contains("Service") ||
                    name.Contains("Web") ||
                    name.Contains("Window") ||
                    name.Contains("ComponentModel")
                    )
                {
                    //排除
                    return true;
                }

                return false;
            }
        }

        return false;
    }

}
